#include "../interface/I_SpatialTree.h"

I_SpatialTree::I_SpatialTree()
{
	Null();
}

I_SpatialTree::~I_SpatialTree()
{
	Release();
}

void I_SpatialTree::Null()
{
	m_pVertex = NULL;
	m_pIndex = NULL;
	m_pPrimIdx = NULL;
	m_pTreeIdx = NULL;	
	
	m_ppBoundingInterval[X] = NULL;
	m_ppBoundingInterval[Y] = NULL;
	m_ppBoundingInterval[Z] = NULL;

	m_pKdTree = NULL;
	m_pBVHTree = NULL;

	m_pInterval = NULL;
	m_pNode = NULL;

	m_pActorData = NULL;

	m_nDepth = 8;
	m_nMaxPrim = 4;
	m_nNode	= 0;
	m_nPrimIdx = 0;
	m_nTreeIdx = 0;
	m_nInterval	= 0;
	m_nTraversalIdx = 0;

	m_nPrimitive = 0;
	m_nVertex = 0;
}

void I_SpatialTree::Release()
{
	delete m_pPrimIdx;
	delete m_ppBoundingInterval[X];
	delete m_ppBoundingInterval[Y];
	delete m_ppBoundingInterval[Z];
	delete m_pTreeIdx;
	delete m_pKdTree;
	delete m_pBVHTree;
	delete m_pInterval;
	delete m_pInterval;
	delete m_pActorData;

	Null();
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

void I_SpatialTree::KdTree_p2(S_TreeNode *pb, S_KdNode * pt, S_TreeNode & bn)
{
	uint32 currTraversalIdx = m_nTraversalIdx;

	m_nTraversalIdx++;

	if (!bn.Leaf())
	{			
		pt[currTraversalIdx].split = bn.split;
		
		KdTree_p2(pb, pt, pb[bn.left]);

		pt[currTraversalIdx].right = m_nTraversalIdx;

		KdTree_p2(pb, pt, pb[bn.right]);
	}
	else
	{
		pt[currTraversalIdx].count = ((bn.end - bn.start) << 2) | TREE_LEAF;
 		pt[currTraversalIdx].start = bn.start;
	}
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

void I_SpatialTree::KdTree_p1()
{
	S_TreeNode * pTree = (S_TreeNode *) m_pNode->hPtr();
	S_KdNode * pS_KdNode = (S_KdNode *) m_pKdTree->hPtr();

	S_TreeNode root = pTree[TREE_ROOT];

	m_nTraversalIdx = TREE_ROOT;

	KdTree_p2(pTree, pS_KdNode, root);
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

void I_SpatialTree::BVHTree_p2(S_TreeNode *pb, S_BVHNode * pn, S_Interval * pi, S_TreeNode & bn, int i)
{
	uint32 currTraversalIdx = m_nTraversalIdx;

	m_nTraversalIdx++;

	if (!bn.Leaf())
	{			
		pn[currTraversalIdx].pmin.x = pi[i * XYZ + X].start;
		pn[currTraversalIdx].pmax.x = pi[i * XYZ + X].end;

		pn[currTraversalIdx].pmin.y = pi[i * XYZ + Y].start;
		pn[currTraversalIdx].pmax.y = pi[i * XYZ + Y].end;

		pn[currTraversalIdx].pmin.z = pi[i * XYZ + Z].start;
		pn[currTraversalIdx].pmax.z = pi[i * XYZ + Z].end;

		pn[currTraversalIdx].split = bn.split;

		BVHTree_p2(pb, pn, pi, pb[bn.left], bn.left);

		pn[currTraversalIdx].right = m_nTraversalIdx + m_pBVHTree->Offset();

		BVHTree_p2(pb, pn, pi, pb[bn.right], bn.right);
	}
	else
	{
		pn[currTraversalIdx].pmin.x = pi[i * XYZ + X].start;
		pn[currTraversalIdx].pmax.x = pi[i * XYZ + X].end;

		pn[currTraversalIdx].pmin.y = pi[i * XYZ + Y].start;
		pn[currTraversalIdx].pmax.y = pi[i * XYZ + Y].end;

		pn[currTraversalIdx].pmin.z = pi[i * XYZ + Z].start;
		pn[currTraversalIdx].pmax.z = pi[i * XYZ + Z].end;

		pn[currTraversalIdx].count = ((bn.end - bn.start) << 2) | TREE_LEAF;
		pn[currTraversalIdx].start = bn.start + m_pTreeIdx->Offset();
	}
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

void I_SpatialTree::BVHTree_p1()
{
	S_TreeNode *pTree     = (S_TreeNode *) m_pNode->hPtr();
	S_BVHNode  *pBVHNode  = (S_BVHNode  *) m_pBVHTree->hPtr();
	S_Interval *pInterval = (S_Interval *) m_pInterval->hPtr();

	S_TreeNode root = pTree[TREE_ROOT];

	m_nTraversalIdx = TREE_ROOT;

	BVHTree_p2(pTree, pBVHNode, pInterval, root, TREE_ROOT);

}